package pro.shushi.pamirs.eip.api.service.impl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.eip.api.IEipApi;
import pro.shushi.pamirs.eip.api.enmu.InterfaceTypeEnum;
import pro.shushi.pamirs.eip.api.model.AbstractEipApi;
import pro.shushi.pamirs.eip.api.model.EipIntegrationInterface;
import pro.shushi.pamirs.eip.api.model.EipOpenInterface;
import pro.shushi.pamirs.eip.api.model.EipRouteDefinition;
import pro.shushi.pamirs.eip.api.service.EipDistributionSupport;
import pro.shushi.pamirs.eip.api.service.EipInterfaceModifyProcessor;
import pro.shushi.pamirs.eip.api.service.EipInterfaceService;
import pro.shushi.pamirs.framework.session.tenant.component.PamirsTenantSession;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.Models;
import pro.shushi.pamirs.meta.common.constants.CharacterConstants;
import pro.shushi.pamirs.middleware.zookeeper.service.ZookeeperService;

@Slf4j
@Component
public class EipZookeeperNodeListener implements TreeCacheListener, InitializingBean {

    @Autowired
    private ZookeeperService zookeeperService;

    @Autowired
    private EipInterfaceService interfaceService;

    private EipInterfaceModifyProcessor registerConsumer;

    private EipInterfaceModifyProcessor cancellationConsumer;

    @Override
    public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
        switch (treeCacheEvent.getType()) {
            case NODE_ADDED:
                addInterface(treeCacheEvent.getData());
                break;
            case NODE_UPDATED:
                updateInterface(treeCacheEvent.getData());
                break;
            case NODE_REMOVED:
                removeInterface(treeCacheEvent.getData());
                break;
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.registerConsumer = (interfaceType, eipApi, isEnable) -> {
            switch (interfaceType) {
                case INTEGRATION:
                    interfaceService.registerInterface((EipIntegrationInterface) eipApi);
                    break;
                case OPEN:
                    interfaceService.registerOpenInterface((EipOpenInterface) eipApi);
                    break;
                case ROUTE:
                    interfaceService.registerRouteDefinition((EipRouteDefinition) eipApi);
                    break;
            }
        };
        this.cancellationConsumer = (interfaceType, eipApi, isEnable) -> {
            switch (interfaceType) {
                case INTEGRATION:
                    interfaceService.cancellationInterface((EipIntegrationInterface) eipApi);
                    break;
                case OPEN:
                    interfaceService.cancellationOpenInterface((EipOpenInterface) eipApi);
                    break;
                case ROUTE:
                    interfaceService.cancellationRouteDefinition((EipRouteDefinition) eipApi);
                    break;
            }
        };
    }

    private void addInterface(ChildData childData) {
        processInterfaceModify(childData, registerConsumer);
    }

    private void updateInterface(ChildData childData) {
        processInterfaceModify(childData, (interfaceType, eipApi, isEnable) -> {
            if (isEnable) {
                registerConsumer.accept(interfaceType, eipApi, Boolean.TRUE);
            } else {
                cancellationConsumer.accept(interfaceType, eipApi, Boolean.FALSE);
            }
        });
    }

    private void removeInterface(ChildData childData) {
        processInterfaceModify(childData, cancellationConsumer);
    }

    private void processInterfaceModify(ChildData childData, EipInterfaceModifyProcessor consumer) {
        String path = childData.getPath();
        int rootPathLength = zookeeperService.getRootPath().length() + EipDistributionSupport.ZOOKEEPER_PARENT_NODE_PATH_PREFIX.length() + 1;
        if (path.length() <= rootPathLength) {
            return;
        }
        path = path.substring(rootPathLength);
        String[] pathList = path.split(CharacterConstants.SEPARATOR_SLASH);
        String tenant;
        if (pathList.length == 3) {
            tenant = pathList[0];
            pathList = new String[]{pathList[1], pathList[2]};
        } else if (pathList.length == 2) {
            tenant = null;
        } else {
            return;
        }
        if (tenant != null) {
            PamirsTenantSession.setTenant(tenant);
        }
        processInterfaceModify(childData, pathList, consumer);
    }

    private void processInterfaceModify(ChildData childData, String[] pathList, EipInterfaceModifyProcessor consumer) {
        InterfaceTypeEnum interfaceType = InterfaceTypeEnum.safeValueOf(pathList[0]);
        if (interfaceType == null) {
            //无效类型忽略
            return;
        }
        IEipApi eipApi = fetchInterface(interfaceType, pathList[1]);
        if (eipApi == null) {
            //无效接口信息忽略
            return;
        }
        byte[] data = childData.getData();
        Boolean isEnable = null;
        // 忽略日志频率配置
        Boolean isIgnoreLogConfig = null;
        if (data != null && data.length == 2) {
            //此处仅处理有效数据变更
            byte data0 = data[0];
            if (data0 == EipDistributionSupport.ENABLED[0]) {
                isEnable = Boolean.TRUE;
            } else if (data0 == EipDistributionSupport.DISABLED[0]) {
                isEnable = Boolean.FALSE;
            }
            byte data1 = data[1];
            if (data1 == EipDistributionSupport.ENABLED[0]) {
                isIgnoreLogConfig = Boolean.TRUE;
            } else if (data1 == EipDistributionSupport.DISABLED[0]) {
                isIgnoreLogConfig = Boolean.FALSE;
            }
        }
        if (isEnable != null && isIgnoreLogConfig != null) {
            ((AbstractEipApi) eipApi).setIsIgnoreLogFrequency(isIgnoreLogConfig);
            //当有效数据变更时调用指定处理逻辑
            consumer.accept(interfaceType, eipApi, isEnable);
        }
    }

    private IEipApi fetchInterface(InterfaceTypeEnum interfaceType, String interfaceName) {
        switch (interfaceType) {
            case INTEGRATION:
                return Models.origin().queryOne(new EipIntegrationInterface().setInterfaceName(interfaceName));
            case OPEN:
                return Models.origin().queryOne(new EipOpenInterface().setInterfaceName(interfaceName));
            case ROUTE:
                return Models.origin().queryOne(new EipRouteDefinition().setInterfaceName(interfaceName));
            default:
                return null;
        }
    }
}
